﻿/*
 * taskagent.cpp
 *
 *  Created on: 2018年2月19日
 *      Author: work
 */

#include <dm/export.hpp>

#define DM_API_OS_SYS DM_API_EXPORT

#include <dm/os/sys/taskagent.hpp>
#include <dm/os/scopelock.hpp>

#include <dm/os/log/logger.hpp>
#include <string>
#include <cstdlib>
#include <signal.h>

namespace dm{
namespace os{
namespace sys{

static const char* logModule = "CTaskAgent.sys.os.dm";

CTaskAgent* CTaskAgent::TaskAgent = NULL;

void sigHandler( int sig ){
	if( CTaskAgent::TaskAgent ){
		log().info(STATICMODULE "收到信号%d退出",sig);
		CTaskAgent::TaskAgent->exit();
		exit(EXIT_SUCCESS);
	}
}

CTaskAgent::CTaskAgent( const char* program,const char* paras ):CSysInfo(CSysInfo::ins()),m_idx(-1){
	if( TaskAgent!=NULL ){
		log().warnning(THISMODULE "只能创建一个对象实例");
		std::exit(EXIT_FAILURE);
	}

	TaskAgent = this;
	log().debug(THISMODULE "创建对象");
	init(program,paras);
}

CTaskAgent::CTaskAgent( const int& argc,char* argv[] ):CSysInfo(CSysInfo::ins()),m_idx(-1){
	if( TaskAgent!=NULL ){
		log().warnning(THISMODULE "只能创建一个对象实例");
		std::exit(EXIT_FAILURE);
	}

	TaskAgent = this;

	log().debug(THISMODULE "创建对象");
	std::string paras;
	for( int i=1;i<argc;++i ){
		if( i!=1 )
			paras += " ";
		paras += argv[i];
	}

	init(argv[0],paras.c_str());
}

CTaskAgent::~CTaskAgent(){
	log().debug(THISMODULE "销毁对象");
	exit();
}

bool CTaskAgent::runOnce(){
	dm::CTimeStamp n = dm::CTimeStamp::cur();

	if( ifSysRunning() ){
		if( m_idx>=0 ){
			STaskInfo& task = m_taskInfos[m_idx];
			dm::os::CScopeLock lock(task.lock);

			if( task.disable==false && task.taskState==TsRunning ){
				task.refreshTs.copy(n);
				return true;
			}else{
				log().info(THISMODULE "任务停止运行");
				task.taskState = TsStoped;
				return false;
			}
		}else
			return true;	// 非受控任务
	}else{
		log().info(THISMODULE "系统未运行");
		return false;
	}
}

void CTaskAgent::exit(){
	if( m_idx>=0 ){
		STaskInfo& task = m_taskInfos[m_idx];
		dm::os::CScopeLock slock(task.lock);
		task.taskState = TsStoped;
	}
}

void CTaskAgent::init( const char* program,const char* paras ){
	dm::CTimeStamp n = dm::CTimeStamp::cur();

	if( !ifSysRunning() ){
		log().warnning(THISMODULE "平台未运行");
		std::exit( EXIT_FAILURE );
	}

	dm::string::CStringRef strr(program);
	int p = strr.lastChars("/\\");
	if( p>=0 )
		program += (p+1);

	int idx = getTaskIndex(program,paras);
	if( idx>=0 ){
		STaskInfo& task = m_taskInfos[idx];
		dm::os::CScopeLock lock( task.lock );

		if( task.disable ){
			log().warnning(THISMODULE "任务禁止执行 %s %s",program,paras);
			std::exit(EXIT_FAILURE);
		}

		if( ifProcess(task.pid) ){
			log().warnning(THISMODULE "任务已经在执行 %s %s",program,paras);
			std::exit(EXIT_FAILURE);
		}

		signal(SIGINT,sigHandler);
		signal(SIGTERM,sigHandler);

		task.taskState = TsRunning;
		task.startTs.copy(n);
		task.refreshTs.copy(n);
#ifdef WIN32
		task.pid = GetCurrentProcessId();
#else
		task.pid = getpid();
#endif

		m_idx = idx;
	}else{
		log().warnning(THISMODULE "不存在任务 %s %s",program,paras);
		std::exit(EXIT_FAILURE);
	}
}

}
}
}
